/*  static char SccsId[] = "@(#)agl.h	1.12   3/18/96";
 *
 *         Copyright (c) KUBOTA Corporation and HUDSON SOFT,
 *                  1994, 1995 All Rights Reserved
 *
 *  This software comprises unpublished confidential information of
 *  KUBOTA Corp. and HUDSON SOFT. It may not be used, copied or made 
 *  available to anyone, except in accordance with the license under
 *  which it is furnished.
 */

#ifndef _AGL_H
#define _AGL_H

#ifndef NULL
#define NULL 0L
#endif

#define AGLTFuncSize		3600		/* 三角関数の最大角度。farl依存 */

#define AGL_LIGHT0	0		/* ライト指定用定義。ライト関連関数で使用 */
#define AGL_LIGHT1	1		/* ライト指定用定義。ライト関連関数で使用 */

typedef short fix187;
typedef short fix1015;

typedef struct Material {
    fix1015	ambient;
    fix1015	diffuse;
    fix1015	specular;
    fix1015	dummy1;
    fix1015	rmat[5];
} Material;

typedef struct object {
    int 	*geometryTop;		/* AGCオブジェクトデータ格納アドレス	*/
    int 	geometryLength;		/* オブジェクトデータ長			*/
    Material 	*material;		/* マテリアルへのポインタ		*/
    int		objChanged;		/* マトリクスの変更フラグ		*/
    fix187	objToWorld187[4][4];	/* ワールド座標系への変換マトリクス	*/
    fix1015	objToWorld1015[3][3];	/* ワールド座標系への変換マトリクス	*/
    short	dummy1;
    fix187 	objMatrix[4][4];	/* オブジェクトマトリックス		*/
    fix1015 	nrmMatrix[3][3];	/* ノーマルマトリクス			*/
    short	dummy2;
} object;

typedef struct camera {
    fix187	camMatrix187[4][4];	/* カメラマトリクス1		*/
    fix1015	camMatrix1015[3][3];	/* カメラマトリクス2		*/
    fix187	camTrans[3][3];		/* Camera Translate Direction */
    int		camChanged;		/* マトリクスの変更フラグ	*/
} camera;

typedef struct light {
    fix1015	lightVector[3];		/* ライトのベクタ		*/
    fix1015	lightStrength;		/* ライトの強さ			*/
    int		lightChanged;		/* ライトの変更フラグ		*/
} light;

/* マクロ定義 */
#define CONV1015TO187(val) ((0x8000& (val))? (0xff80 | ((val)>>8)) : ((val)>>8))

#define AGLResetCamera() { AGLSetNUnitMatrix3((fix187*)__AGLCamera.camTrans); \
	 __AGLCamera.camChanged = -2; }

#define AGLPerspectiveCamera(prs) { \
	if (__AGLCamera.camChanged == -2) { \
		AGLSetUnitMatrix4((fix187*)__AGLCamera.camMatrix187);\
		__AGLCamera.camMatrix187[3][2] = (prs);\
		__AGLCamera.camChanged = -1; \
	} else { \
		FarlSetSrcMatrix((unsigned short*)__AGLCamera.camMatrix187); \
		FarlPerseZ4x4M187(prs); \
		FarlCopyDstToMem4x4((unsigned short*)__AGLCamera.camMatrix187); \
	} \
	}

#define AGLZoomCamera(zx, zy, zz) { \
	if (__AGLCamera.camChanged == -2) { \
		FarlGetScale4x4M187( (zx), (zy), (zz), \
			(unsigned short*)__AGLCamera.camMatrix187); \
		__AGLCamera.camChanged = -1; \
	} else { \
		FarlSetSrcMatrix((unsigned short*)__AGLCamera.camMatrix187); \
		FarlScale4x4M187((zx), (zy), (zz)); \
		FarlCopyDstToMem4x4((unsigned short*)__AGLCamera.camMatrix187); \
	} \
	}

#define AGLResetLight(ln) {\
	__AGLLight[ln].lightVector[0] = 0;\
	__AGLLight[ln].lightVector[1] = 0;\
	__AGLLight[ln].lightVector[2] = 0x7fff;\
	__AGLLight[ln].lightChanged = 1;\
	}

#define AGLSetLightVector(ln, vx, vy, vz) {\
	__AGLLight[ln].lightVector[0] = (vx);\
	__AGLLight[ln].lightVector[1] = (vy);\
	__AGLLight[ln].lightVector[2] = (vz);\
	__AGLLight[ln].lightChanged = 1;\
	}

#define AGLSetLightStrength(ln, str) {\
	__AGLLight[ln].lightStrength = (str);\
	__AGLLight[ln].lightChanged = 1;\
	}

#define AGLSetLight(ln, vx, vy, vz, str) {\
	AGLSetLightVector(ln, vx, vy, vz);\
	AGLSetLightStrength(ln, str);\
	}

#define AGLResetObj(obj) { (obj)->objChanged = -2; }

#define AGLScaleObj(obj, sx, sy, sz) {\
	if ((obj)->objChanged == -2) {\
		FarlGetScale4x4M187( (sx), (sy), (sz), \
			(unsigned short*)((obj)->objToWorld187)); \
		(obj)->objChanged = -1;\
	} else {\
		FarlSetSrcMatrix((unsigned short*)((obj)->objToWorld187));\
		FarlScale4x4M187((sx), (sy), (sz));\
		FarlCopyDstToMem4x4((fix187*)(obj)->objToWorld187);\
	}\
	}

#define AGLTranslateObj(obj, dx, dy, dz) {\
	if ((obj)->objChanged == -2) {\
		FarlGetTranslate4x4M187( (dx), (dy), (dz), \
			(unsigned short*)((obj)->objToWorld187)); \
		(obj)->objChanged = -1;\
	} else {\
		FarlSetSrcMatrix((unsigned short*)((obj)->objToWorld187));\
		FarlTranslate4x4M187((dx), (dy), (dz));\
		FarlCopyDstToMem4x4((fix187*)((obj)->objToWorld187));\
	}\
	}

#define AGLFixPutObj(obj) { AGLFixObj(obj); AGLPutObj(obj); }

/* オブジェクト制御。モデル座標系→ワールド座標系の変換を制御する */
int	AGLInit( void );
void	AGLRotateObjX( object*, int);
void	AGLRotateObjY( object*, int);
void	AGLRotateObjZ( object*, int);
void	AGLRotateObjXSC( object*, fix1015, fix1015);
void	AGLRotateObjYSC( object*, fix1015, fix1015);
void	AGLRotateObjZSC( object*, fix1015, fix1015);
void	AGLObjMulMatrix( object*, fix187[4][4], fix1015[3][3]);
void	AGLSetMaterial(Material*, int);

/* ライト制御。ワールド座標系で定義する */
void	AGLRotateLightX( int, int);
void	AGLRotateLightY( int, int);
void	AGLRotateLightZ( int, int);
void	AGLRotateLightXSC( int, fix1015, fix1015);
void	AGLRotateLightYSC( int, fix1015, fix1015);
void	AGLRotateLightZSC( int, fix1015, fix1015);
void	AGLLightMulMatrix( int, fix1015[3][3]);

/* カメラ制御。ワールド座標系→ビュー座標系の変換を制御する */
void	AGLTranslateCamera(fix187, fix187, fix187);
void	AGLLookAtCamera( fix187, fix187, fix187, fix1015, fix1015, fix1015);
void	AGLRotateCameraX( int);
void	AGLRotateCameraY( int);
void	AGLRotateCameraZ( int);
void	AGLRotateCameraXSC( fix1015, fix1015);
void	AGLRotateCameraYSC( fix1015, fix1015);
void	AGLRotateCameraZSC( fix1015, fix1015);
void	AGLCameraMulMatrix( fix187 [4][4] , fix1015[3][3]);

/* 描画、その他 */
void	AGLFixObj( object* );
void	AGLPutObj( object* );
void	AGLShot( void );

void	AGLDrawLightVector(int, short);
void	AGLDispObj(object*);
void	AGLDispCamera(void);
void	AGLDispLight(void);
void	AGLSetUnitMatrix4(fix187*);
void	AGLSetUnitMatrix3(fix1015*);
void	AGLSetNUnitMatrix3(fix187*);

/* AGLライブラリ用グローバル変数 */
extern camera		__AGLCamera;
extern light		__AGLLight[2];

#endif	/* _AGL_H */
